#include "Common.hpp"
#include "Socket.hpp"
#include <memory>
#include <poll.h>
#include <wait.h>
#include <functional>
#include <sys/select.h>
#define FDSIZE 1024
int const fd_default = -1;
using namespace SocketMoudule;
using ioservice_t = function<void(shared_ptr<Socket> &, InetAddr &)>;
class TcpServer
{
public:
    TcpServer(uint16_t port)
        : _port(port), _listensockptr(make_unique<TcpSocket>(port)), _isrunning(false)
    {
        _listensockptr->BuildTcpServerMoudule(_port);
        for (int i = 0; i < FDSIZE; i++)
        {
            _fds[i].fd=fd_default;
            _fds[i].events=0;
            _fds[i].revents=0;
        }
        _fds[0].fd=_listensockptr->Fd();
        _fds[0].events=POLLIN;
    }
    void SolveAccept()
    {
        InetAddr client;
        auto sock = _listensockptr->Accept(&client);
        for (int i = 0; i < FDSIZE; i++)
        {
            if (_fds[i].fd == fd_default)
            {
                _fds[i].fd = sock->Fd();
                _fds[i].events = POLLIN;
                LOG(Level::INFO)<<"accept success fd = "<<sock->Fd();
                break;
            }
            else
            {
                if (i == FDSIZE - 1)
                {
                    LOG(Level::WARING) << "fd fill...";
                    sock->Close();
                }
            }
        }
    }
    void SolveRead(int fd)
    {
        char buffer[1024];
        int n = recv(fd, buffer, sizeof(buffer) - 1, 0);
        if (n == 0)
        {
            _fds[fd].fd = fd_default;
            close(fd);
            cout << "client " << fd << " out..." << endl;
        }
        else if (n < 0)
        {
            _fds[fd].fd = fd_default;
            close(fd);
            cout << "client " << fd << "recv fail" << endl;
        }
        else
        {
            buffer[n] = '\0';
            cout << "client say@: " << buffer <<endl;
        }
    }
    void Start(ioservice_t callout)
    {
        _isrunning = true;
        while (_isrunning)
        {
            int tm = 2000;
            int n = poll(_fds, FDSIZE, tm);
            if (n < 0)
            {
                perror("poll fail\n");
                exit(POLL_ERRO);
            }
            else if (n == 0)
            {
                cout << "overtime..." << endl;
            }
            else
            {
                if (_fds[0].revents & POLLIN)
                {
                    SolveAccept();
                }
                for (int i = 1; i < FDSIZE; i++)
                {
                    if (_fds[i].fd == fd_default)
                        continue;
                    if (_fds[i].revents & POLLIN)
                        SolveRead(_fds[i].fd);
                }
            }
            // SolveFd(fd);
            //  InetAddr client;
            //  auto sock = _listensockptr->Accept(&client);
            //  if (sock == nullptr)
            //  {
            //      LOG(Level::WARING) << "client accept fail";
            //      continue;
            //  }
            //  int id = fork();
            //  if (id < 0)
            //  {
            //      LOG(Level::FATAL) << "fork fail";
            //      exit(FORK_ERRO);
            //  }
            //  else if (id == 0)
            //  {
            //      _listensockptr->Close();
            //      if (fork() > 0)
            //          exit(SUCCESS);
            //      callout(sock,client);
            //      exit(SUCCESS);
            //  }
            //  else
            //  {
            //      sock->Close();
            //      waitpid(id,nullptr,0);
            //  }
        }
    }

private:
    uint16_t _port;
    unique_ptr<Socket> _listensockptr;
    bool _isrunning;
    struct pollfd _fds[FDSIZE];
};